package cc.avatar.model;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import cc.avatar.util.TemporalCollection;

/**
 * 指实际参与业务活动的内部个体或单位，不包括客户，它们都有帐务条目
 * <ul>
 * 本系统共有三种角色,每个Party只能为其中一种
 * </ul>
 * <li>销售员</li> <li>生产班组</li> <li>运输班组</li> <li>收款人</li> </ul>
 * 
 * @author jchai.cn@gmail.com
 */
@Entity
@Table(name = "t_party")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Party {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	private String name;	
	private String phoneNumber;
	private boolean active;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name = "party_id")
	@OrderBy(value = "effectiveTime desc")
	private Set<PersistentPostingRule> persistentRules = new HashSet<PersistentPostingRule>();

	@Enumerated(EnumType.STRING)
	private AccountingRole role;

	public AccountingRole getRole() {
		return role;
	}

	public void setRole(AccountingRole role) {
		this.role = role;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPhoneNumber() {
		return phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	public Set<PersistentPostingRule> getPersistentRules() {
		return persistentRules;
	}

	public void setAccountingRules(Set<PersistentPostingRule> persistentRules) {
		this.persistentRules = persistentRules;
	}

	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}

	@Transient
	private TemporalCollection postingRules = new TemporalCollection();

	@SuppressWarnings("unchecked")
	private void registerRules(){
		if (this.persistentRules == null) return;
		try {
			for (PersistentPostingRule config : this.persistentRules) {
				Class clz = Class.forName(config.getClassName());
				Class cx[] = { String.class };
				PostingRule rule = (PostingRule) clz.getConstructor(cx)
						.newInstance(new Object[] { config.getParameters() });
				addPostingRule(rule, config.getEffectiveTime());
			}
		} catch (Exception e) {
            throw new BusinessException("设置帐务规则出错 " + e.getMessage());
		}
	}
	
	// 将规则插入已有相应事件类型的有效时间段容器中
	private void addPostingRule(PostingRule rule, Date date) {
		postingRules.put(date, rule);
	}

	// 返回某一时刻的计费规则。
	public PostingRule getPostingRule(Date when) {
		registerRules();
		PostingRule r = (PostingRule) postingRules.get(when);
		// 使用默认的运费算法
		if (r == null) {
			throw new IllegalArgumentException("未发现 " + this.getName()
					+ " 的帐务规则在时间点 " + when);
		}
		return r;
	}
	
	public void addRule(PersistentPostingRule rule){
		rule.setCreatedTime(new Date());
		this.persistentRules.add(rule);
	}
	
	@Override
	public String toString(){
		return this.name;
	}
}
